import sys
import os
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit, QTabWidget, QMessageBox, QFileDialog, QFormLayout, QGroupBox, QTableWidget, QTableWidgetItem, QSizePolicy)
from PyQt5.QtCore import Qt, pyqtSignal, QTimer
from PyQt5.QtGui import QFont, QPalette, QColor, QPixmap, QPainter
from PyQt5.QtCore import Qt
from PyQt5.QtMultimedia import QMediaPlayer, QMediaContent
import configparser
from database import DatabaseManager
from ticket_generator import TicketGenerator
from ticket_checker import TicketChecker
from export_manager import ExportManager

import pygame

class SecondaryDisplay(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()
        self.reset_timer = QTimer(self)
        self.reset_timer.setSingleShot(True)
        self.reset_timer.timeout.connect(self.reset_to_default_status)
        
    def init_ui(self):
        self.setWindowTitle('检票状态显示')
        self.setStyleSheet('background-color: white;')
        
        layout = QVBoxLayout()
        layout.setAlignment(Qt.AlignCenter)
        
        # 创建图标标签
        self.icon_label = QLabel()
        self.icon_label.setAlignment(Qt.AlignCenter)
        self.icon_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        
        # 创建文本标签
        self.text_label = QLabel('请刷码/卡')
        self.text_label.setAlignment(Qt.AlignCenter)
        self.text_label.setStyleSheet('font-size: 3vw; font-weight: bold; color: #000000;')
        self.text_label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
        
        # 加载默认图标
        self.load_icon('icons/card.png')
        
        # 添加到布局
        layout.addWidget(self.icon_label)
        layout.addWidget(self.text_label)
        
        self.setLayout(layout)
        
    def resizeEvent(self, event):
        # 窗口大小改变时重新调整图标大小
        if hasattr(self, 'current_icon_path'):
            self.load_icon(self.current_icon_path)
        super().resizeEvent(event)
        
    def reset_to_default_status(self):
        self.update_status('', 'default')
        
    def load_icon(self, icon_path):
        # 构建完整路径
        base_dir = os.path.dirname(os.path.abspath(__file__))
        full_path = os.path.join(base_dir, icon_path)
        
        if not os.path.exists(full_path):
            self.text_label.setText('请刷码/卡')
            return
            
        pixmap = QPixmap(full_path)
        if pixmap.isNull():
            self.text_label.setText('无效的图片文件')
            return
            
        # 调整图片大小为窗口宽度的40%，保持比例
        target_size = int(self.width() * 0.4)
        scaled_pixmap = pixmap.scaled(target_size, target_size, Qt.KeepAspectRatio, Qt.SmoothTransformation)
        self.icon_label.setPixmap(scaled_pixmap)
        self.current_icon_path = icon_path
          
    def update_status(self, status_text, status_type):
        icon_map = {
            'success': 'icons/check.png',
            'error': 'icons/error.png',
            'default': 'icons/card.png'
        }
        
        icon_path = icon_map.get(status_type, icon_map['default'])
        self.load_icon(icon_path)
        # 设置状态文本
        text_map = {
            'success': '检票成功',
            'error': '检票失败',
            'default': '请刷码/卡'
        }
        status_text = text_map.get(status_type, text_map['default'])
        self.text_label.setText(status_text)
        
        # 设置文本颜色
        color_map = {
            'success': '#008000',  # 绿色
            'error': '#FF0000',    # 红色
            'default': '#000000'   # 黑色
        }
        color = color_map.get(status_type, color_map['default'])
        self.text_label.setStyleSheet(f'color: {color}; font-size: 3vw; font-weight: bold;')
        
        # 成功或失败状态1秒后重置
        if status_type in ['success', 'error']:
            self.reset_timer.start(1000)

class TicketCheckerUI(QWidget):
    status_updated = pyqtSignal(str, str)  # 定义状态更新信号 (状态文本, 状态类型)
    def __init__(self, db_manager, config, sound_success, sound_repeat, sound_failure):
        super().__init__()
        self.db_manager = db_manager
        self.config = config
        self.sound_success = sound_success
        self.sound_repeat = sound_repeat
        self.sound_failure = sound_failure
        self.init_ui()
        
    def init_ui(self):
        main_layout = QVBoxLayout(self)
        main_layout.setAlignment(Qt.AlignCenter)
        main_layout.setContentsMargins(50, 50, 50, 50)

        # 标题
        title_label = QLabel('票务核验')
        title_label.setStyleSheet('font-size: 24px; font-weight: bold; margin-bottom: 30px;')
        title_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(title_label)

        # 提示文本
        prompt_label = QLabel('请在下方输入二维码数据')
        prompt_label.setStyleSheet('font-size: 16px; margin-bottom: 20px;')
        prompt_label.setAlignment(Qt.AlignCenter)
        main_layout.addWidget(prompt_label)

        # 输入框
        self.ticket_input = QLineEdit()
        self.ticket_input.setPlaceholderText('在此输入二维码数据')
        self.ticket_input.setStyleSheet('padding: 10px; font-size: 14px; border-radius: 5px; border: 1px solid #ccc;')
        self.ticket_input.setFixedWidth(300)
        self.ticket_input.returnPressed.connect(self.check_ticket)
        main_layout.addWidget(self.ticket_input, alignment=Qt.AlignCenter)

        # 核验按钮
        check_btn = QPushButton('核验')
        check_btn.setStyleSheet('''
            QPushButton {
                background-color: #1E90FF;
                color: white;
                border: none;
                border-radius: 5px;
                padding: 10px 20px;
                font-size: 16px;
                margin-top: 20px;
            }
            QPushButton:hover {
                background-color: #4169E1;
            }
        ''')
        check_btn.clicked.connect(self.check_ticket)
        main_layout.addWidget(check_btn, alignment=Qt.AlignCenter)

        # 核验结果
        self.check_result = QTextEdit()
        self.check_result.setReadOnly(True)
        main_layout.addWidget(QLabel('核验结果:'), alignment=Qt.AlignLeft)
        main_layout.addWidget(self.check_result)
        
    def showEvent(self, event):
        super().showEvent(event)
        # 当界面显示时自动聚焦到输入框
        self.ticket_input.setFocus()

    def check_ticket(self):
        ticket_data = self.ticket_input.text()
        aes_key = self.config.get('Database', 'aes_key')
        if not all([ticket_data, aes_key]):
            QMessageBox.warning(self, '警告', '请输入二维码数据')
            return
        
        try:
            checker = TicketChecker(self.db_manager)
            result = checker.check(ticket_data, aes_key)
            self.check_result.setText(result)
            # 清空输入框
            self.ticket_input.clear()
            
            # 播放相应的声音
            if '首次入场' in result and self.sound_success:
                self.sound_success.play()
                self.status_updated.emit('票券有效', 'success')
            elif '重复入场' in result and self.sound_repeat:
                self.sound_repeat.play()
                self.status_updated.emit('票券已使用', 'error')
            elif '失败' in result and self.sound_failure:
                self.sound_failure.play()
                self.status_updated.emit('票券无效', 'error')
            else:
                self.status_updated.emit('请刷码/卡', 'default')
        except Exception as e:
            QMessageBox.critical(self, '错误', f'核验失败: {str(e)}')
            if self.sound_failure:
                self.sound_failure.play()

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('蓝冰检票系统')
        self.setGeometry(100, 100, 800, 600)
        
        import os
        base_dir = os.path.dirname(os.path.abspath(__file__))
        # 初始化pygame音频
        pygame.mixer.init()
        # 初始化声音文件
        self.sound_success = None
        success_path = os.path.join(base_dir, 'sound', '1.wav')
        if os.path.exists(success_path):
            try:
                self.sound_success = pygame.mixer.Sound(success_path)
            except pygame.error as e:
                print(f"加载成功音效失败: {e}")
        else:
            print(f"音频文件不存在: {success_path}")

        self.sound_repeat = None
        repeat_path = os.path.join(base_dir, 'sound', '2.wav')
        if os.path.exists(repeat_path):
            try:
                self.sound_repeat = pygame.mixer.Sound(repeat_path)
            except pygame.error as e:
                print(f"加载重复音效失败: {e}")
        else:
            print(f"音频文件不存在: {repeat_path}")

        self.sound_failure = None
        failure_path = os.path.join(base_dir, 'sound', '3.wav')
        if os.path.exists(failure_path):
            try:
                self.sound_failure = pygame.mixer.Sound(failure_path)
            except pygame.error as e:
                print(f"加载失败音效失败: {e}")
        else:
            print(f"音频文件不存在: {failure_path}")
        
        # 初始化配置
        self.config = configparser.ConfigParser()
        self.config_file = os.path.join(base_dir, 'config.ini')
        self.load_config()
        
        # 初始化数据库连接
        self.db_manager = DatabaseManager(self.config)
        
        # 初始化导出管理器
        self.export_manager = ExportManager(self.db_manager)
        
        # 创建主部件和布局
        self.central_widget = QWidget()
        self.setCentralWidget(self.central_widget)
        self.main_layout = QVBoxLayout(self.central_widget)
        
        # 创建选项卡控件
        self.tabs = QTabWidget()
        self.home_tab = QWidget()
        home_layout = QVBoxLayout(self.home_tab)
        home_layout.setAlignment(Qt.AlignCenter)
        
        # 添加标题
        title_label = QLabel('检票软件')
        title_label.setStyleSheet('font-size: 36px; font-weight: bold; color: #333;')
        home_layout.addWidget(title_label)
        
        # 添加说明文字
        desc_label = QLabel('票务核验系统')
        desc_label.setStyleSheet('font-size: 18px; color: #666; margin-top: 10px;')
        home_layout.addWidget(desc_label)
        
        # 添加进入按钮
        enter_btn = QPushButton('进入系统')
        enter_btn.setStyleSheet('padding: 10px 20px; font-size: 16px; margin-top: 30px;')
        enter_btn.clicked.connect(lambda: self.tabs.setCurrentIndex(1))
        home_layout.addWidget(enter_btn)
        
        # 添加版权信息
        copyright_label = QLabel('© 蓝冰检票系统 版权所有')
        copyright_label.setStyleSheet('font-size: 12px; color: #999; margin-top: 50px;')
        copyright_label.setAlignment(Qt.AlignBottom | Qt.AlignCenter)
        home_layout.addWidget(copyright_label)
        
        self.tabs.addTab(self.home_tab, '首页')

        # 创建各个功能选项卡
        self.check_tab = TicketCheckerUI(self.db_manager, self.config, self.sound_success, self.sound_repeat, self.sound_failure)
        self.tabs.addTab(self.check_tab, '票务核验')
        self.create_generator_tab()
        self.create_export_tab()
        self.create_library_tab()
        self.tabs.setCurrentIndex(0)  # 默认显示首页选项卡

        self.main_layout.addWidget(self.tabs)

        # 创建副屏显示窗口
        self.secondary_display = SecondaryDisplay()
        # 连接状态更新信号
        self.check_tab.status_updated.connect(self.update_secondary_display)
        # 尝试将副屏移动到第二个显示器
        self.setup_secondary_display()

    def setup_secondary_display(self):
        # 获取所有可用屏幕
        screens = QApplication.desktop().screenCount()
        if screens > 1:
            # 如果有第二个屏幕，将副屏移动到第二个屏幕
            screen_geometry = QApplication.desktop().screenGeometry(1)
            self.secondary_display.move(screen_geometry.left(), screen_geometry.top())
            self.secondary_display.resize(screen_geometry.width(), screen_geometry.height())
            self.secondary_display.showFullScreen()
        else:
            # 否则在主屏幕显示为窗口
            self.secondary_display.resize(800, 600)
            self.secondary_display.show()

    def update_secondary_display(self, status_text, status_type):
        self.secondary_display.update_status(status_text, status_type)
        
    def load_config(self):
        if os.path.exists(self.config_file):
            self.config.read(self.config_file, encoding='utf-8')
            # Add aes_key if not exists
            if not self.config.has_option('Database', 'aes_key'):
                self.config.set('Database', 'aes_key', '')
                self.save_config()
        else:
            # 创建默认配置
            self.config['Database'] = {
                'host': 'localhost',
                'user': 'root',
                'password': '',
                'database': 'ticket_system',
                'aes_key': ''
            }
            with open(self.config_file, 'w') as f:
                self.config.write(f)
        
    def save_config(self):
        with open(self.config_file, 'w') as f:
            self.config.write(f)
        QMessageBox.information(self, '成功', '数据库配置已保存')
        
    def create_database_dialog(self):
        dialog = QDialog(self)
        dialog.setWindowTitle('数据库设置')
        layout = QFormLayout(dialog)
        
        self.host_input = QLineEdit(self.config.get('Database', 'host'))
        self.user_input = QLineEdit(self.config.get('Database', 'user'))
        self.password_input = QLineEdit(self.config.get('Database', 'password'))
        self.password_input.setEchoMode(QLineEdit.Password)
        self.db_name_input = QLineEdit(self.config.get('Database', 'database'))
        self.aes_key_input = QLineEdit(self.config.get('Database', 'aes_key'))
        self.aes_key_input.setEchoMode(QLineEdit.Password)
        
        layout.addRow('AES密钥:', self.aes_key_input)
        layout.addRow('主机:', self.host_input)
        layout.addRow('用户名:', self.user_input)
        layout.addRow('密码:', self.password_input)
        layout.addRow('数据库名:', self.db_name_input)
        
        btn_layout = QHBoxLayout()
        test_btn = QPushButton('测试连接')
        test_btn.clicked.connect(self.test_db_connection)
        save_btn = QPushButton('保存配置')
        save_btn.clicked.connect(self.save_db_config)
        init_btn = QPushButton('初始化数据库')
        btn_layout.addWidget(test_btn)
        btn_layout.addWidget(save_btn)
        btn_layout.addWidget(init_btn)
        layout.addRow(btn_layout)
        
        dialog.exec_()
        layout = QFormLayout(dialog)  # 正确初始化布局管理器

        # 原输入控件迁移至对话框
        host_input = QLineEdit(self.config.get('Database', 'host'))
        user_input = QLineEdit(self.config.get('Database', 'user'))
        password_input = QLineEdit(self.config.get('Database', 'password'))
        password_input.setEchoMode(QLineEdit.Password)
        db_name_input = QLineEdit(self.config.get('Database', 'database'))
        aes_key_input = QLineEdit(self.config.get('Database', 'aes_key'))
        aes_key_input.setEchoMode(QLineEdit.Password)

        # 正确添加控件到布局
        layout.addRow('主机:', host_input)
        layout.addRow('用户名:', user_input)
        layout.addRow('密码:', password_input)
        layout.addRow('数据库名:', db_name_input)
        layout.addRow('AES密钥:', aes_key_input)

        # 测试连接和保存按钮
        test_btn = QPushButton('测试连接')
        save_btn = QPushButton('保存配置')
        btn_layout = QHBoxLayout()
        btn_layout.addWidget(test_btn)
        btn_layout.addWidget(save_btn)
        layout.addRow(btn_layout)

        # 绑定按钮点击事件（使用lambda传递输入值）
        test_btn.clicked.connect(lambda: self.test_db_connection(
            host_input.text(), user_input.text(), password_input.text(), db_name_input.text()
        ))
        save_btn.clicked.connect(lambda: self.save_db_config(
            host_input.text(), user_input.text(), password_input.text(), db_name_input.text(), aes_key_input.text()
        ))

        dialog.exec_()

    def create_menu_bar(self):
        menu_bar = self.menuBar()
        settings_menu = menu_bar.addMenu('设置')
        db_action = settings_menu.addAction('数据库设置')
        db_action.triggered.connect(self.create_database_dialog)
        
    def test_db_connection(self, host, user, password, db_name):
        temp_config = {
            'host': host,
            'user': user,
            'password': password,
            'database': db_name
        }
        if DatabaseManager.test_connection(temp_config):
            QMessageBox.information(self, '成功', '数据库连接测试成功')
        else:
            QMessageBox.critical(self, '错误', '数据库连接测试失败')
        
    def save_db_config(self, host, user, password, db_name, aes_key):
        self.config['Database']['host'] = host
        self.config['Database']['user'] = user
        self.config['Database']['password'] = password
        self.config['Database']['database'] = db_name
        self.config['Database']['aes_key'] = aes_key
        self.save_config()
        self.db_manager.update_config(self.config)
        
    def create_generator_tab(self):
        self.gen_tab = QWidget()
        self.tabs.addTab(self.gen_tab, '票务生成')
        
        layout = QVBoxLayout()
        self.gen_tab.setLayout(layout)
        
        form_group = QGroupBox('生成参数')
        form_layout = QFormLayout()
        form_group.setLayout(form_layout)
        
        self.prefix_input = QLineEdit()
        self.count_input = QLineEdit()
        self.aes_key_input = QLineEdit(self.config.get('Database', 'aes_key'))
        self.aes_key_input.setEchoMode(QLineEdit.Password)
        form_layout.addRow('前缀:', self.prefix_input)
        form_layout.addRow('数量:', self.count_input)
        
        generate_btn = QPushButton('生成票务')
        generate_btn.clicked.connect(self.generate_tickets)
        
        self.result_display = QTextEdit()
        self.result_display.setReadOnly(True)
        
        layout.addWidget(form_group)
        layout.addWidget(generate_btn)
        layout.addWidget(QLabel('生成结果:'))
        layout.addWidget(self.result_display)
        
    def generate_tickets(self):
        prefix = self.prefix_input.text()
        count = self.count_input.text()
        aes_key = self.config.get('Database', 'aes_key')
        if not all([prefix, count, aes_key]):
            QMessageBox.warning(self, '警告', '请填写所有参数')
            return
        
        try:
            count = int(count)
            generator = TicketGenerator(self.db_manager, aes_key)
            result = generator.generate(prefix, count)
            self.result_display.setText('\n'.join(result))
            QMessageBox.information(self, '成功', f'已生成{count}个票务')
        except ValueError:
            QMessageBox.warning(self, '警告', '数量必须是整数')
        except Exception as e:
            QMessageBox.critical(self, '错误', f'生成失败: {str(e)}')
        


    def init_database(self):
        if self.db_manager.init_database():
            QMessageBox.information(self, '成功', '数据库初始化成功')
        else:
            QMessageBox.critical(self, '错误', '数据库初始化失败')
        
    def create_library_tab(self):
        self.library_tab = QWidget()
        layout = QVBoxLayout(self.library_tab)
        
        # 创建表格显示票库信息
        self.ticket_table = QTableWidget()
        self.ticket_table.setColumnCount(5)
        self.ticket_table.setHorizontalHeaderLabels(['ID', '票号', '状态', '入场时间', '操作'])
        self.ticket_table.horizontalHeader().setStretchLastSection(True)
        layout.addWidget(self.ticket_table)
        
        # 刷新按钮
        refresh_btn = QPushButton('刷新票库')
        refresh_btn.clicked.connect(self.refresh_ticket_library)
        layout.addWidget(refresh_btn)
        
        self.tabs.addTab(self.library_tab, '票库管理')
        
        # 初始加载票库数据
        self.refresh_ticket_library()
    
    def refresh_ticket_library(self):
        # 查询所有票据
        tickets = self.db_manager.execute_query("SELECT id, ticket_number, entry_state, entry_time FROM tickets ORDER BY id DESC")
        
        if not tickets:
            self.ticket_table.setRowCount(0)
            return
        
        self.ticket_table.setRowCount(len(tickets))
        
        for row, ticket in enumerate(tickets):
            # 状态显示文本
            state_text = '未使用'
            if ticket['entry_state'] == 1:
                state_text = '已使用'
            elif ticket['entry_state'] == 2:
                state_text = '黑名单'
            
            # 设置表格内容
            self.ticket_table.setItem(row, 0, QTableWidgetItem(str(ticket['id'])))
            self.ticket_table.setItem(row, 1, QTableWidgetItem(ticket['ticket_number']))
            self.ticket_table.setItem(row, 2, QTableWidgetItem(state_text))
            self.ticket_table.setItem(row, 3, QTableWidgetItem(str(ticket['entry_time']) if ticket['entry_time'] else ''))
            
            # 创建操作按钮
            btn_layout = QHBoxLayout()
            
            # 撤销使用按钮
            undo_btn = QPushButton('撤销使用')
            undo_btn.setFixedSize(100, 35)
            undo_btn.setEnabled(ticket['entry_state'] == 1)
            undo_btn.clicked.connect(lambda checked, id=ticket['id']: self.update_ticket_state(id, 0))
            btn_layout.addWidget(undo_btn)
            
            # 添加/移除黑名单按钮
            blacklist_btn = QPushButton('添加黑名单' if ticket['entry_state'] != 2 else '移除黑名单')
            blacklist_btn.setFixedSize(100, 35)
            target_state = 2 if ticket['entry_state'] != 2 else 0
            blacklist_btn.clicked.connect(lambda checked, id=ticket['id'], state=target_state: self.update_ticket_state(id, state))
            btn_layout.addWidget(blacklist_btn)
            
            # 将按钮添加到表格单元格
            btn_widget = QWidget()
            btn_widget.setLayout(btn_layout)
            self.ticket_table.setCellWidget(row, 4, btn_widget)
    
    def update_ticket_state(self, ticket_id, state):
        # 更新票据状态
        success = self.db_manager.execute_update(
            "UPDATE tickets SET entry_state = %s WHERE id = %s",
            (state, ticket_id)
        )
        
        if success:
            QMessageBox.information(self, '成功', '票据状态已更新')
            self.refresh_ticket_library()
        else:
            QMessageBox.critical(self, '失败', '票据状态更新失败')
    
    def create_export_tab(self):
        self.export_tab = QWidget()
        self.tabs.addTab(self.export_tab, '数据导出')
        
        layout = QVBoxLayout()
        self.export_tab.setLayout(layout)
        
        info_label = QLabel('点击下方按钮将所有票务数据导出为CSV文件')
        layout.addWidget(info_label)
        
        export_btn = QPushButton('导出CSV')
        export_btn.clicked.connect(self.export_tickets)
        export_btn.setStyleSheet('font-size: 16px; padding: 10px;')
        
        self.export_result = QLabel('')
        
        layout.addWidget(export_btn, alignment=Qt.AlignCenter)
        layout.addWidget(self.export_result, alignment=Qt.AlignCenter)
        layout.addStretch()
        
    def export_tickets(self):
        success, message = self.export_manager.export_to_csv()
        self.export_result.setText(message)
        if success:
            QMessageBox.information(self, '成功', message)
        else:
            QMessageBox.warning(self, '警告', message)
        
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())